import numpy as np
import pandas as pd


# 线性回归函数
def standRegres(dataSet):
    xMat = np.mat(dataSet.iloc[:, :-1].values)  # 提取特征
    yMat = np.mat(dataSet.iloc[:, -1].values).T  # 提取标签
    xTx =  xMat.T * xMat
    if np.linalg.det(xTx) == 0:
        print('This matrix is singular,cannot do inverse')  # 行列式为0,则该矩阵为奇异矩阵,无法求解逆矩阵
        return

    ws = xTx.I * (xMat.T * yMat)
    return ws


def sseCal(dataSet, regres):
    n = dataSet.shape[0]
    y = dataSet.iloc[:, -1].values
    ws = regres(dataSet)
    yhat = dataSet.iloc[:, :-1].values * ws
    yhat = yhat.flatten()
    SSE = np.power(yhat - y, 2).sum()

    return SSE


def rSquare(dataSet, regres):
    sse = sseCal(dataSet, regres)
    y = dataSet.iloc[:, -1].values
    sst = np.power(y - y.mean(), 2).sum()
    return 1 - sse / sst


# todo: error?
def ridgeRegres(dataSet, lam=0.2):
    xMat = np.mat(dataSet.iloc[:, :-1].values)
    yMat = np.mat(dataSet.iloc[:, -1].values).T
    xTx = xMat.T * xMat
    denom = xTx + np.eye(xMat.shape[1]) * lam
    ws = denom.I * (xMat.T * yMat)
    return ws


aba = pd.read_csv('abalone.csv', header=None)
print('aba.head():\n', aba.head())

aba.columns = ['Sex', 'Length', 'Diameter', 'Height', 'Whole weight', 'Shucked weight', 'Viscera weight',
               'Shell weight', 'Rings']

aba.iloc[:, 0] = 1
print('aba.head():\n', aba.head())

rws = ridgeRegres(aba)
print('rws:\n', rws)

standRegres(aba)

rSquare(aba, ridgeRegres)
rSquare(aba, standRegres)

from sklearn.linear_model import Ridge

ridge = Ridge(alpha=0.2)
ridge.fit(aba.iloc[:, :-1], aba.iloc[:, -1])

print('ridge.coef_:\n', ridge.coef_)  # 查看系数
print('ridge.intercept_:\n', ridge.intercept_)  # 查看截距

from sklearn.linear_model import RidgeCV

Ridge_ = RidgeCV(alphas=np.arange(1, 1001, 100),
                 scoring="r2",
                 store_cv_values=True  # ,cv=5
                 )
Ridge_.fit(aba.iloc[:, :-1], aba.iloc[:, -1])
# ⽆关交叉验证的岭回归结果
Ridge_.score(aba.iloc[:, :-1], aba.iloc[:, -1])
# 调⽤所有交叉验证的结果
print('Ridge_.cv_values_.shape:\n', Ridge_.cv_values_.shape)
# 进⾏平均后可以查看每个正则化系数取值下的交叉验证结果
Ridge_.cv_values_.mean(axis=0)
# 查看被选择出来的最佳正则化系数
print('Ridge_.alpha_:\n', Ridge_.alpha_)
